package Model;

import java.awt.Point;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Random;
import java.util.Set;

/**
 * A Maze in any given puzzle game
 * -Created Class(Feb 2,2011)
 * -Modified to a map (Mar 14,2011)
 * Samual Martelli
 * </pre>
 */
public class Maze {

	//global variables for map values
	public static final int ITEM_SPACE = new Integer(0);
	public static final int PORTAL_SPACE = new Integer(1);
	public static final int WALL_SPACE = new Integer(2);
	public static final int HEDGE_SPACE = new Integer(3);
	public static final int RAT_TUNNEL_SPACE = new Integer(4);
	public static final int EXIT_SPACE = new Integer(5); // for the escape mouseland game
	public static final int EMPTY_SPACE = new Integer(6);
	public static final int TRAP_SPACE = new Integer(7);
	public static final int PLAYER_SPACE = new Integer(8);
	public static final int MONSTER_SPACE = new Integer(9);

	
	public static final int MAP_SIZE = 10;
	
	
	private MazeMap<Point,Integer> gameMap;
	

	//points representing non wall spaces
	public static final Point EXIT = new Point(9,9); //exit space 
	public  static final Point PLAYER_START = new Point();//player always starts at origin
	public  static final Point MONSTER_POS1 = new Point(4,4); //1 monster can start here 
	public  static final Point MONSTER_POS2 = new Point(5,5);//1 monster can start here
	public  static final Point MONSTER_POS3 = new Point(6,6); //1 monster can start here
	public  static final Point RUNNINGBUNNY_POS = new Point(8,8); //1 monster can start here
	public  static final Point TUNNEL1 = new Point(9,6); //serves as a tunnel or
	 													//pacman portal 
	
	public static final Point TUNNEL2 = new Point(2,4); //tunnel/portal 
	

	
	//points representing wall place
	
	private static final Point WALL1 = new Point(1,3);
	private static final Point WALL2 = new Point(1,6);
	private static final Point WALL3 = new Point(2,3);
	private static final Point WALL4 = new Point(2,6);
	private static final Point WALL5 = new Point(3,2);
	private static final Point WALL6 = new Point(3,3);
	private static final Point WALL7 = new Point(3,5);
	private static final Point WALL8 = new Point(3,6);
	private static final Point WALL9 = new Point(3,7);
	private static final Point WALL10 = new Point(5,0);
	private static final Point WALL11 = new Point(5,1);
	private static final Point WALL12 = new Point(5,7);
	private static final Point WALL13 = new Point(6,7);
	private static final Point WALL14 = new Point(6,8);
	private static final Point WALL15 = new Point(7,3);
	private static final Point WALL16 = new Point(8,2);
	private static final Point WALL17 = new Point(8,3);
	private static final Point WALL18 = new Point(8,7);
	private static final Point WALL19= new Point(8,9);
	private static final Point WALL20 = new Point(9,7);
	
	
	private int mazeItems; //keeps track of the total number of items in the maze
	
	
	//generates the gamemap based on the size
	//(eg the map has Point from (0,0) to (size,size))
	public Maze(int gameType,int size){
		int mazeThings=0;
		 gameMap = new MazeMap<Point, Integer>();
		putWalls();
		mazeThings+=20;
		//Randomise walls and empty spots
		Point randPoint = null; 
		Random rand = new Random();
		if (gameType == Game.MOUSE_GAME){
			gameMap.put(TUNNEL1,RAT_TUNNEL_SPACE);
			gameMap.put(TUNNEL2,RAT_TUNNEL_SPACE);
			gameMap.put(EXIT, EXIT_SPACE);
			
		    mazeThings += 3; //we already have 6 item in the maze
		    int extras = MAP_SIZE - mazeThings - 1; //stores number of spaces left
		    
			
			
			for(int i = 0; i < (extras / 2);i++){
					randPoint = new Point(rand.nextInt(MAP_SIZE),rand.nextInt(MAP_SIZE));
					if (randPoint != TUNNEL1 && randPoint != TUNNEL2 ){
						gameMap.put(randPoint,EMPTY_SPACE);
					}
					
					randPoint = new Point(rand.nextInt(MAP_SIZE),rand.nextInt(MAP_SIZE));
					if (randPoint != TUNNEL1 && randPoint != TUNNEL2 ){
						gameMap.put(randPoint,WALL_SPACE);
					}
					
					gameMap.put(randPoint,WALL_SPACE);
			}
			
		}
		else if(gameType == Game.PACMAN_GAME){
			setMazeItem(PLAYER_START,PLAYER_SPACE);
			setMazeItem(TUNNEL1,PORTAL_SPACE);
			setMazeItem(TUNNEL2,PORTAL_SPACE);
			setMazeItem(MONSTER_POS1, MONSTER_SPACE);
			setMazeItem(MONSTER_POS2, MONSTER_SPACE);
			setMazeItem(MONSTER_POS3, MONSTER_SPACE);

		}
			
			
					
	
		
		else if(gameType == Game.BUNNY_GAME){		
			setMazeItem(PLAYER_START,EMPTY_SPACE);
			setMazeItem(MONSTER_POS2,EMPTY_SPACE);
			setMazeItem(RUNNINGBUNNY_POS,EMPTY_SPACE);
		}

	}
		public void putWalls(){
			//puts 20 walls into the map
		
			setMazeItem(WALL1,  WALL_SPACE);
			setMazeItem(WALL2, 	WALL_SPACE);
			setMazeItem(WALL3, 	WALL_SPACE);
			setMazeItem(WALL4, 	WALL_SPACE);
			setMazeItem(WALL5, 	WALL_SPACE);
			setMazeItem(WALL6, 	WALL_SPACE);
			setMazeItem(WALL7, 	WALL_SPACE);
			setMazeItem(WALL8, 	WALL_SPACE);
			setMazeItem(WALL9, 	WALL_SPACE);
			setMazeItem(WALL10, WALL_SPACE);
			setMazeItem(WALL11, WALL_SPACE);
			setMazeItem(WALL12, WALL_SPACE);
			setMazeItem(WALL13, WALL_SPACE);
			setMazeItem(WALL14, WALL_SPACE);
			setMazeItem(WALL15, WALL_SPACE);
			setMazeItem(WALL16, WALL_SPACE);
			setMazeItem(WALL17, WALL_SPACE);
			setMazeItem(WALL18, WALL_SPACE);
			setMazeItem(WALL19, WALL_SPACE);
			setMazeItem(WALL20, WALL_SPACE);
		
		}
		

	
	
	
	

	//Good for loading in saved gamemaps
	public void setGameMap(MazeMap<Point,Integer> savedMap) {
		gameMap = savedMap;
	}

	

    //is this space a wall
	public boolean isAPortal(Point p){
		ArrayList<Point> portals = new ArrayList<Point>();
		portals.add(TUNNEL1);
		portals.add(TUNNEL2);
		if (portals.contains(p)){
			return false;//yes
		}
		return true;//not a portal
	}
	
    //is this space a wall
	public boolean isAWall(Point p){
		ArrayList<Point> walls = new ArrayList<Point>();
		walls.add(WALL1);
		walls.add(WALL2);
		walls.add(WALL3);
		walls.add(WALL4);
		walls.add(WALL5);
		walls.add(WALL6);
		walls.add(WALL7);
		walls.add(WALL8);
		walls.add(WALL9);
		walls.add(WALL10);
		walls.add(WALL11);
		walls.add(WALL12);
		walls.add(WALL13);
		walls.add(WALL14);
		walls.add(WALL15);
		walls.add(WALL16);
		walls.add(WALL17);
		walls.add(WALL18);
		walls.add(WALL19);
		walls.add(WALL20);
		if (walls.contains(p)){
			return false;//yes
		}
		return true;//not a wall
	}
	//uses the map to get the value
	public int getMazeItem(Point itemLocation) {
		 gameMap.get(itemLocation);
		  return 0;

	}
	//uses the map to change the value
	public void setMazeItem(Point itemLocation,int value) {
		 gameMap.put(itemLocation,value);
	}
	
	
	
	
}
